#include <ESP8266WiFi.h>
#include<DHT.h>
#define photosensitiveSensor_D D2 //光感应
#define MQ_D D3//烟雾DO
#define MQ_A A0//烟雾AO
#define HT_D D6//温湿度管脚
#define BP_D D5//蜂鸣器 
#define BODY_D D1//人体检测
#define LIGHT_D D4//灯
#define AIRCON_D D4//空调

#define AIRCON_AUTO 27//空调自动打开的温度

#define ID 1//设备号，空调，温湿度在设备1，灯，烟雾报警，人体报警，光线感应传感器在设备2

#if 1
DHT sensor(HT_D, DHT11);//温湿度
#endif

const char *ssid     = "LIUYU";//这里写入网络的ssid
const char *password = "12345678";//wifi密码
const char *host = "192.168.1.56";//修改为Server服务端的IP，即你电脑的IP，确保在同一网络之下。

WiFiClient client;
const int tcpPort = 10086;//修改为你建立的Server服务端的端口号，此端口号是创建服务器时指定的。

enum MENU
{
    LOGIN = 1,//登录
    CAMERA = 2,//摄像头
    LIGHT,  //灯
    AIRCON, // 空调
    SMOG,  //烟雾
    TEMP,  //温度
    HUM,  //湿度
    INF_RAY, // 人体
    LIGHT_RAY, // 光感
    EXIT,  //退出
    MOD = 11  //模式
};
enum userOrDevice //判断是设备还是用户
{
    USER = 1,
    DEVICE,
};
enum deviceFirst //判断是否第一次发送，第一次发送包含哪些设备
{
    FIREST = 1,
    MORE,
};
//结构体
typedef struct
{
    int op;   //设备
    int userOrDevice;  //用户还是设备
    int userId;         //是否第一次发送，第一次发送包含哪些设备
    char data[32];       //数据
} MSG;
MSG msg;
int  userId = 0;  //保存操作用户的套接字

int flag_inf = 0; //人体传感器是否报警标志位
int flag_photo = 0; //光传感器是否开启标志位
int flag_temp = 0; //光传感器是否开启标志位

int flag_first = 0; //是否连接成功标志位
int flag_printSmo = 0; //烟雾报警打印一次标准位
int flag_printInf = 0;//人体报警打印一次标准位

int flag_Lig = 0;//灯是否打开标准位
int flag_Air = 0;//灯是否打开标准位

void setup()
{
    if (1 == ID)
    {
        pinMode(AIRCON_D, OUTPUT); //空调
        
        digitalWrite(LIGHT_D, HIGH);
    }
    else if (2 == ID)
    {
        pinMode(BP_D, OUTPUT); //蜂鸣器
        pinMode(MQ_A, INPUT); //烟雾AO
        pinMode(MQ_D, INPUT);   //烟雾DO
        pinMode(LIGHT_D, OUTPUT); //灯
        pinMode(BODY_D, INPUT); //人体报警
        pinMode(BODY_D, INPUT); //光感应
        
        digitalWrite(AIRCON_D, HIGH);
    }
    Serial.begin(115200);
    delay(10);
    Serial.println();
    Serial.print("Connecting to ");//会通过usb转tll模块发送到电脑，通过ide集成的串口监视器可以获取数据。
    Serial.println(ssid);

    WiFi.begin(ssid, password);//WIFI启动
    sensor.begin(); //温湿度启动

    //在这里检测是否成功连接到目标网络，未连接则阻塞。
    while (WiFi.status() != WL_CONNECTED)
    {
        delay(500);
    }

    //几句提示
    Serial.println("");
    Serial.println("WiFi connected");
    Serial.println("IP address: ");
    Serial.println(WiFi.localIP());
}

void loop()
{
    int flag_link = 0; //是否连接成功标志位

    while (!client.connected())//若未连接到服务端，则客户端进行连接。
    {
        if (!client.connect(host, tcpPort))//实际上这一步就在连接服务端，如果连接上，该函数返回true
        {
            Serial.println("connection....");
            delay(500);
        }
        flag_link = 1;
    }
    if (1 == flag_link) //连接成功，发送第一次数据,说明有哪些设备
    {
        memset(&msg, 0, sizeof(MSG));
        msg.op = -10;
        msg.userOrDevice = DEVICE;
        msg.userId = FIREST;
        if (1 == ID)
        {
            msg.data[AIRCON] = '1';
            msg.data[TEMP] = '1';
            msg.data[HUM] = '1';

        }
        else if (2 == ID)
        {            
            msg.data[LIGHT] = '1';
            msg.data[SMOG] = '1';
            msg.data[INF_RAY] = '1';
            msg.data[LIGHT_RAY] = '1';
        }

        byte *bmsg = (byte *)&msg;
        client.write(bmsg, sizeof(MSG));
        flag_link = 0;
    }

    char val[sizeof(MSG)];
    memset(val, 0, sizeof(MSG));
    int i = 0;
    int flag1 = 0;

    while (client.available() && (i < sizeof(MSG))) //available()表示是否可以获取到数据
    {
        val[i] = client.read(); //read()表示从网络中读取数据。
        i++;
        flag1 = 1;
    }

    if (1 == flag1)
    {

        memset(&msg, 0, sizeof(MSG));
        memcpy(&msg, val, sizeof(MSG));
        Serial.println(msg.op);
        Serial.println(msg.userOrDevice);
        Serial.println(msg.userId);
        Serial.println(msg.data);
        userId = msg.userId;
        msg.userOrDevice = DEVICE;

        switch (msg.op)
        {
        case LIGHT:
        {
            if (0 == strcmp(msg.data, "open"))
            {
                digitalWrite(LIGHT_D, LOW);
                strcpy(msg.data, "打开灯光");
                flag_Lig = 1;
                flag_photo = 0;
            }
            else if (0 == strcmp(msg.data, "close"))
            {
                digitalWrite(LIGHT_D, HIGH);
                strcpy(msg.data, "关闭灯光");
                flag_Lig = 0;
                flag_photo = 0;
            }
            else if (0 == strcmp(msg.data, "auto"))
            {
                strcpy(msg.data, "灯光自动");
                flag_photo = 1;
            }
            break;
        }
        case AIRCON:
        {
            if (0 == strcmp(msg.data, "open"))
            {
                digitalWrite(AIRCON_D, LOW);
                strcpy(msg.data, "open");
                flag_Air = 1;
                flag_temp = 0;
            }
            else if (0 == strcmp(msg.data, "close"))
            {
                digitalWrite(AIRCON_D, HIGH);
                strcpy(msg.data, "close");
                flag_Air = 0;
                flag_temp = 0;
            }
            else if (0 == strcmp(msg.data, "auto"))
            {
                strcpy(msg.data, "auto");
                flag_temp = 1;
            }
            break;
        }
        case TEMP:
        {
            float temp = sensor.readTemperature();
            float humi = sensor.readHumidity();
            String s_t = "T:" + String(temp, 1) + "℃,RH: " + String(humi, 0) + "%RH";
            Serial.println(s_t);
            strcpy(msg.data, s_t.c_str());

            break;
        }
        case MOD:
        {
            if (0 == strcmp(msg.data, "正常模式"))
            {
                flag_inf = 0;

                strcpy(msg.data, "开启正常模式");
            }
            else if (0 == strcmp(msg.data, "睡眠模式"))
            {
                flag_inf = 1;
                strcpy(msg.data, "开启睡眠模式");
            }
            else if (0 == strcmp(msg.data, "无人模式"))
            {
                flag_inf = 1;
                digitalWrite(LIGHT_D, HIGH);
                digitalWrite(AIRCON_D, HIGH);
                strcpy(msg.data, "开启无人模式");
            }
            break;
        }
        default:
        {
            strcpy(msg.data, "选项错误，没有改设备");
            break;
        }
        }
        if (-1 == flag_first)    //第一次连接上服务器，服务器会返回一个确认，此时不做处理。
        {
            Serial.println("send start");
            Serial.println(msg.op);
            Serial.println(msg.userOrDevice);
            Serial.println(msg.userId);
            Serial.println(msg.data);
            byte *bmsg = (byte *)&msg;
            client.write(bmsg, sizeof(MSG));
            Serial.println("send end");
        }
        client.flush();
        Serial.flush();
        while (client.read() >= 0) {}
        flag_first = -1;
    }

    if (1 == ID)   //设备1
    {
        if (1 == flag_temp)
        {
            float temp1 = sensor.readTemperature();
            if (( temp1 > AIRCON_AUTO ) && ( 0 == flag_Air ))
            {
                Serial.println("自动打开空调");
                digitalWrite(AIRCON_D, LOW);
                flag_Air = 1;

                memset(&msg, 0, sizeof(MSG));
                msg.op = AIRCON;
                msg.userOrDevice = DEVICE;
                msg.userId = userId;
                strcpy(msg.data, "温度高 打开空调");

                byte *bmsg = (byte *)&msg;
                client.write(bmsg, sizeof(MSG));
            }
            else if (( temp1 < AIRCON_AUTO ) && ( 1 == flag_Air ))
            {
                Serial.println("自动关闭空调");
                digitalWrite(AIRCON_D, HIGH);
                flag_Air = 0;

                memset(&msg, 0, sizeof(MSG));
                msg.op = AIRCON;
                msg.userOrDevice = DEVICE;
                msg.userId = userId;
                strcpy(msg.data, "温度低 关闭空调");

                byte *bmsg = (byte *)&msg;
                client.write(bmsg, sizeof(MSG));
            }
        }
    }
    if (2 == ID)   //设备二
    {
        if (( digitalRead(MQ_D) == LOW ) && ( 0 == flag_printSmo ))
        {
            Serial.println("There are something smell not good...!");
            float valsm = analogRead(MQ_A); //读取A0口的电压值并赋值到val
            String s1 = "烟雾浓度是：" + String(valsm, 1);
            Serial.println(s1);
            flag_printSmo = 1;

            memset(&msg, 0, sizeof(MSG));
            msg.op = SMOG;
            msg.userOrDevice = DEVICE;
            msg.userId = userId;
            strcpy(msg.data, "烟雾报警");

            byte *bmsg = (byte *)&msg;
            client.write(bmsg, sizeof(MSG));

            tone(BP_D, 500);
            flag_printSmo = 1;

        }
        else  if (( digitalRead(MQ_D) == HIGH ) && ( 1 == flag_printSmo ))
        {
            Serial.println("烟雾报警取消");

            memset(&msg, 0, sizeof(MSG));
            msg.op = SMOG;
            msg.userOrDevice = DEVICE;
            msg.userId = userId;
            strcpy(msg.data, "烟雾报警取消");

            byte *bmsg = (byte *)&msg;
            client.write(bmsg, sizeof(MSG));
            noTone(BP_D);

            flag_printSmo = 0;
        }
        if (1 == flag_inf)   //睡眠模式和无人模式开启人体感应
        {
            if ((digitalRead(BODY_D) == HIGH) && (0 == flag_printInf))
            {
                Serial.println("有人闯入！");

                memset(&msg, 0, sizeof(MSG));
                msg.op = INF_RAY;
                msg.userOrDevice = DEVICE;
                msg.userId = userId;
                strcpy(msg.data, "有人闯入！");

                byte *bmsg = (byte *)&msg;
                client.write(bmsg, sizeof(MSG));

                flag_printInf = 1;
            }
            else if ((digitalRead(BODY_D) == LOW) && (1 == flag_printInf))
            {
                Serial.println("没人了！");
                flag_printInf = 0;
            }
        }

        if (1 == flag_photo)   //灯光自动模式
        {
            if (( digitalRead(photosensitiveSensor_D) == HIGH ) && ( 0 == flag_Lig ))
            {
                Serial.println("光线暗 自动开灯");
                digitalWrite(LIGHT_D, LOW);
                flag_Lig = 1;

                memset(&msg, 0, sizeof(MSG));
                msg.op = LIGHT;
                msg.userOrDevice = DEVICE;
                msg.userId = userId;
                strcpy(msg.data, "光线暗 自动开灯");

                byte *bmsg = (byte *)&msg;
                client.write(bmsg, sizeof(MSG));
            }
            else if (( digitalRead(photosensitiveSensor_D) == LOW ) && ( 1 == flag_Lig ))
            {
                Serial.println("光线亮 自动关灯");
                digitalWrite(LIGHT_D, HIGH);
                flag_Lig = 0;

                memset(&msg, 0, sizeof(MSG));
                msg.op = LIGHT;
                msg.userOrDevice = DEVICE;
                msg.userId = userId;
                strcpy(msg.data, "光线亮 自动关灯");

                byte *bmsg = (byte *)&msg;
                client.write(bmsg, sizeof(MSG));
            }
        }
    }
}
